/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.gtugs.service;

import org.gtugs.domain.Chapter;
import org.gtugs.repository.ChapterDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author jasonacooper@google.com (Jason Cooper)
 */
@Service("chapterManager")
public class SimpleChapterManager implements ChapterManager {

  private static final String CHAPTER_MEMCACHE_KEY = "chapter";
  private static final String CHAPTERS_MEMCACHE_KEY = "chapters";
  private static final String ACTIVE_CHAPTERS_MEMCACHE_KEY = "activechapters";
  private static final String CHAPTER_COUNT_MEMCACHE_KEY = "chaptercount";
  private static final String CHAPTERS_GROUPED_BY_COUNTRY_MEMCACHE_KEY =
      "chaptersgroupedbycountry";

  @Autowired
  private ChapterDao chapterDao;

  public Integer getChapterCount() {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();

    if (!ms.contains(CHAPTER_COUNT_MEMCACHE_KEY)) {
      ms.put(CHAPTER_COUNT_MEMCACHE_KEY, chapterDao.getChapterCount());
    }

    return (Integer) ms.get(CHAPTER_COUNT_MEMCACHE_KEY);
  }

  public Chapter getChapter(Long id) {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();
    String key = CHAPTER_MEMCACHE_KEY + id;

    if (!ms.contains(key)) {
      ms.put(key, chapterDao.getChapter(id));
    }

    return (Chapter) ms.get(key);
  }

  public List<Chapter> getChapters() {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();

    if (!ms.contains(CHAPTERS_MEMCACHE_KEY)) {
      ms.put(CHAPTERS_MEMCACHE_KEY, chapterDao.getChapters());
    }

    return (List<Chapter>) ms.get(CHAPTERS_MEMCACHE_KEY);
  }

  public List<Chapter> getActiveChapters() {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();

    if (!ms.contains(ACTIVE_CHAPTERS_MEMCACHE_KEY)) {
      ms.put(ACTIVE_CHAPTERS_MEMCACHE_KEY, chapterDao.getActiveChapters());
    }

    return (List<Chapter>) ms.get(ACTIVE_CHAPTERS_MEMCACHE_KEY);
  }

  public List<Chapter> getChapters(Set<Long> ids) {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();
    Set<Long> idsToFetch = new HashSet<Long>();

    List<Chapter> chapters = new ArrayList<Chapter>(ids.size());
    for (Long id : ids) {
      if (ms.contains(CHAPTER_MEMCACHE_KEY + id)) {
        chapters.add((Chapter) ms.get(CHAPTER_MEMCACHE_KEY + id));
      } else {
        idsToFetch.add(id);
      }
    }

    if (idsToFetch.size() > 0) {
      List<Chapter> fetchedChapters = chapterDao.getChapters(idsToFetch);
      for (Chapter chapter : fetchedChapters) {
        ms.put(CHAPTER_MEMCACHE_KEY + chapter.getId(), chapter);
        chapters.add(chapter);
      }
    }

    return chapters;
  }

  public List<List<Chapter>> getChaptersGroupedByCountry() {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();

    if (!ms.contains(CHAPTERS_GROUPED_BY_COUNTRY_MEMCACHE_KEY)) {
      List<Chapter> chapters = chapterDao.getChaptersOrderedByCountry();
      if (chapters == null) {
        return null;
      }

      List<List<Chapter>> groups = new ArrayList<List<Chapter>>();
      List<Chapter> group = new ArrayList<Chapter>();
      String country = chapters.get(0).getCountry();

      for (Chapter chapter : chapters) {
        if (!chapter.getCountry().equals(country)) {
          groups.add(group);
          group = new ArrayList<Chapter>();
          country = chapter.getCountry();
        }

        group.add(chapter);
      }

      groups.add(group);

      ms.put(CHAPTERS_GROUPED_BY_COUNTRY_MEMCACHE_KEY, groups);
    }
    

    return (List<List<Chapter>>) ms.get(
        CHAPTERS_GROUPED_BY_COUNTRY_MEMCACHE_KEY);
  }

  public void storeChapter(Chapter chapter) {
    MemcacheService ms = MemcacheServiceFactory.getMemcacheService();

    chapterDao.storeChapter(chapter);

    ms.delete(CHAPTERS_MEMCACHE_KEY);
    ms.delete(ACTIVE_CHAPTERS_MEMCACHE_KEY);
    if (chapter.getId() != null) {
      ms.delete(CHAPTER_MEMCACHE_KEY + chapter.getId());
    }
    ms.delete(CHAPTER_COUNT_MEMCACHE_KEY);
    ms.delete(CHAPTERS_GROUPED_BY_COUNTRY_MEMCACHE_KEY);
  }

  public void setChapterDao(ChapterDao chapterDao) {
    this.chapterDao = chapterDao;
  }
}
